import {Button, Form, Input, List, Spin} from "antd";
import React, {FC, useCallback, useEffect, useMemo, useRef, useState} from "react";
import {useTranslation} from "react-i18next";
import {AxiosSer} from "../../services/HttpService";
import {addOkModal, closeModal, updataModalFooter} from "../../services/ModalService";
import {createFetchParams, formatLocaleStr, isString} from "../../utils";
import useStateRef from "../../customUse/useStateRef";
import "./css/BaseSubmit.less";
import useThrottle from "../../customUse/useThrottle";
import Config from "../../Config";
import BaseForm from "../../module/form/BaseForm.tsx";
import {getFormView, getFormViewList} from "../../services/ViewService.tsx";

interface BaseSubmitProps {
    menuId: string,
    modalKey: string,
    isDelete: boolean,
    flowData: any[],
    titleKey: string,
    valKey: string,
    view: string,
    nameKey: string,
    url: string,
    method: string,
    pName: string,
    extend?: any,
    dataSource: any,
    isBatch?: boolean,
    onOk?: Function,
    msgKey: string,
    descKey?: string,
    descPlaceholder?: string,
    descRequired?: boolean,
    isMessBool: any
}

const BaseSubmit: FC<BaseSubmitProps> = (props) => {
    const {t} = useTranslation();

    const dataRef = useRef([]);
    const fromRef = useRef([]);
    const viewRef = useRef([]);
    const [form] = Form.useForm();
    const [list, setList] = useStateRef([], dataRef),
        [view, setView] = useStateRef([], viewRef),
        [loading, setLoading] = useState<boolean>(false);


    const onOk: Function = useThrottle(async () => {
        let {msgKey = "msg", method = "POST", descKey, isMessBool = true, valKey = 'id', pName = 'ids', view} = props,
            fetchParams: any = createFetchParams(props), otherParams: any = {};

        if (view) {
            const values: any = await fromRef.current.validateFields();
            otherParams = {
                ...values,
                ...otherParams
            }
        }
        if (descKey) {
            await form.validateFields()
            otherParams[descKey] = form.getFieldValue(descKey)
        }
        let result: any;
        setLoading(true)
        if (props.onOk) {
            result = await props.onOk(fetchParams, otherParams);
        } else {
            if (!fetchParams.url) {
                if (props.unUrlIsFinish) {
                    await closeModal(props.modalKey, async () => {
                        return {data: fetchParams.params};
                    })
                }
                setLoading(false);
                return false;
            }
            result = await AxiosSer(fetchParams.url, method, {
                ...fetchParams.params, ...otherParams,
                [Config.axiosSerMenuKey]: props.menuId
            }, isMessBool);
        }
        setLoading(false);
        const {code, err_list}: { code: string, msg: string, err_list: any[] } = result;
        if (code === "1") {
            return await closeModal(props.modalKey, () => {
                return {...result};
            })
        }
        if (!err_list || !err_list.length) {
            return
        }
        let newList: any[] = JSON.parse(JSON.stringify(dataRef.current));
        err_list.forEach((item: any) => {
            if (!!item.i) {
                newList[fetchParams.params[pName].indexOf(item[valKey])][msgKey] = item.msg;
            } else {
                newList[item.i][msgKey] = item.msg;
            }
        });
        updataModalFooter(props.modalKey, [<Button key="finish" type="primary"
                                                   onClick={() => closeModal(props.modalKey, () => ({
                                                       ...result
                                                   }))}>{t("complete")}</Button>])
        setList(newList);
    }, 2000, [props.onOk, props]);

    useEffect(() => {
        const {nameKey = "name", valKey = "id", flowData = []}: {
            nameKey: string,
            valKey: string,
            flowData: any[]
        } = props;

        setList(flowData.map((item: any) => {
            return {
                ...item,
                id: item[valKey],
                name: formatLocaleStr(nameKey, item)
            }
        }));
    }, [props.flowData])

    const loadView: Function = useCallback(async (editData: any) => {
        const {view, dataSource}: { view: any, dataSource: any } = props;
        if (isString(view)) {
            let result = await getFormView(view, editData, dataSource);
            setView(result.form);
        } else {
            setView((await getFormViewList(view, editData)).form);
        }
    }, [props]);

    const init: Function = useCallback(async () => {
        if (props.view) {
            loadView()
        }
    }, [props.view]);

    useEffect(() => {
        init()
    }, [props.view]);

    useEffect(() => {
        addOkModal(props.modalKey, onOk);
    }, []);

    const renderTitle = useMemo(() => {
        if (!props.titleKey) {
            return null;
        }
        return (<div className="sf_core_base_submit_title">
            {t(props.titleKey)}
        </div>)
    }, [props.titleKey]);

    const renderDesc = useMemo(() => {
        if (!props.descKey) {
            return null
        }
        const {descRequired = true}: { descRequired: boolean } = props;
        return (
            <Form form={form}>
                <Form.Item
                    name={props.descKey}
                    wrapperCol={{span: 24}}
                    rules={[{required: descRequired, message: t("notNull")}]}
                >
                    <Input.TextArea style={{height: 120}}
                                    placeholder={t(props.descPlaceholder) || t("placeholder")}></Input.TextArea>
                </Form.Item>
            </Form>
        )
    }, [props.descKey, props.descPlaceholder]);

    const renderForm = useMemo(() => {
        if (!view.length) {
            return null
        }
        const {formItemLayout, labelWidth}: {
            formItemLayout: any,
            labelWidth: number,
            className?: string
        } = props;
        return (
            <BaseForm
                init={fromRef}
                labelWidth={labelWidth}
                formItemLayout={formItemLayout}
                view={view}
            />
        )
    }, [view])

    const renderList = useMemo(() => {
        const {msgKey = "msg", nameKey, isDelete = false}: {
            msgKey: string,
            nameKey: string,
            isDelete: boolean
        } = props;
        if (!nameKey) {
            return null
        }
        return (
            <List
                size="small"
                bordered
                className="sf_core_base_submit_list"
                dataSource={dataRef.current}
                renderItem={(item: any) => {
                    return <List.Item>
                        <List.Item.Meta
                            title={item.name}
                            description={<>
                                {isDelete && item.children && item.children.length ?
                                    <span style={{color: 'red'}}>{t("hasChildrenIsDelete")}</span> : null}
                                <span style={{color: 'red'}}>{item[msgKey]}</span>
                            </>}
                        />
                    </List.Item>
                }}
            />
        )
    }, [list, props.msgKey, props.nameKey, props.isDelete]);

    const renderBatchSubmit = useMemo(() => {
        return (
            <Spin spinning={loading} wrapperClassName={"sf_core_base_submit"}>
                {renderTitle}
                {renderDesc}
                {renderForm}
                {renderList}
            </Spin>
        )
    }, [props, list, loading, view])
    return (renderBatchSubmit);
};

export default BaseSubmit;